#ifndef CHANNEL_H_
#define CHANNEL_H_

#include <cassert>
#include <functional>

#include "netlib/base/noncopyable.h"
#include "netlib/base/time_stamp.h"

namespace netlib::net {

class EventLoop;

class Channel : NonCopyable {
public:
	using EventCallback = std::function<void()>;
	using ReadEventCallback = std::function<void(Timestamp)>;

	Channel(EventLoop* loop, int fd) : loop_(loop), kFd(fd) {}
	~Channel() {
		assert(!is_handling_);
		// close(fd_);
	}

	int Fd() const { return kFd; }
	int Events() const { return events_; }
	void SetRevents(int revents) { revents_ = revents; }
	bool IsNoneEvent() const { return events_ == kNoneEvent; }
	int Index() const { return index_; }
	void SetIndex(int idx) { index_ = idx; }
	EventLoop* OwnerLoop() const { return loop_; }

	void SetReadCallback(const ReadEventCallback& rcb) { read_callback_ = rcb; }
	void SetWriteCallback(const EventCallback& wcb) { write_callback_ = wcb; }
	void SetErrorCallback(const EventCallback& ecb) { error_callback_ = ecb; }
	void SetCloseCallback(const EventCallback& ccb) { close_callback_ = ccb; }
	bool IsWriting() const { return events_ & kWriteEvent; }

	void HandleEvent(Timestamp /*time*/);
	void EnableWriting() {
		events_ |= kWriteEvent;
		Update();
	}
	void EnableReading() {
		events_ |= kReadEvent;
		Update();
	}
	void DisableWriting() { events_ &= (~kWriteEvent); }
	void DisableAll() {
		events_ = kNoneEvent;
		Update();
	}
	void Remove();

private:
	void Update();

	// bool is_added_to_loop_;
	bool is_handling_{false};
	EventLoop* loop_;
	const int kFd;
	int events_{0};
	int revents_{0};
	int index_{-1};

	ReadEventCallback read_callback_;
	EventCallback write_callback_;
	EventCallback error_callback_;
	EventCallback close_callback_;

	static const int kNoneEvent;
	static const int kReadEvent;
	static const int kWriteEvent;
};

} // namespace netlib::net

#endif // CHANNEL_H_